[Android][Framework] 全方位理解Android权限之底层实现概览


0000 目录

这个阶段搞了很多和Android文件权限相关的问题,虽然一知半解,但也算是对Android权限机制有一些自己的理解。遂将这些内容整理出来。因为权限这部分涉及到的内容很多,故将知识分为几块内容分别去整理。目前能想到的概要如下(现在因为进度原因有些修改):

  1. Android 权限底层实现原理概述
  2. Android 权限系统一
  3. Android uid,gid的生成与权限机制的联系
  4. Android packageManagerService与权限的千丝万缕(源码解析)
  5. Android 从recovery模式下的OTA升级理解权限
  6. Android ROOT 原理
  7. Android 签名
  8. Android 权限大杀器 — Selinux的策略

这是第一篇。2,3,4已经有一些草稿了,但离发出来还有一些时间。5,6,7还在规划中。可以关注新弄的公众号softard,后面比较完善的文章都会在这个号上及时更新。当然一些普通的随笔还是在wossoneri.github.io的博客更新。

0001 Overview

Linux File Permission

众所周知,Android的内核是linux的内核。对于linux来说,系统的一切都是文件。同时,linux为文件系统设计了一套完善的权限机制。下面简单提一下linux文件权限的核心:

比如在Android手机adb shell下查看一个目录

# ls -ld data/data/
drwxrwx--x 113 system system 4096 1970-01-01 15:08 data/data/

其中,drwxrwx--x这10位代表文件权限,第一位文件类型可以忽略(这里类型是文件夹),后面每三位代表文件拥有的权限,包括rwx(可读,可写,可执行)。system system表示文件属于system用户和属于system组。

翻译过来是,system用户对该文件拥有读写执行权限,system组对该文件拥有读写执行权限,其他用户对该文件拥有执行权限。简单来说就是771权限。

Android Permission

Permission权限是Android系统定义的一套权限机制,用于控制APP访问某个硬件设备或某个Android系统的组件。
举两个常见的例子:

  1. 如果你的App想要访问存储卡,你需要在你的AndroidManifest文件中使用对应的permission用于向系统请求权限 。
  2. 你可以给你的Activity组件加个自定义的访问权限,这样任何想启动该Activity的程序必须在它的AndroidManifest中进行权限的请求。见Android自定义权限

那么为什么你在AndroidManifest文件请求storage权限你就可以访问设备文件?linux文件属性的权限和Permission到底是怎么联系起来的呢?下面我们来具体来讲。

0010 packages.list & packages.xml

Android开机阶段会扫描所有App,从Manifest文件中把App信息和权限存到packages.xmlpackages.list文件中,具体的处理过程会在后面第三篇去分析。

因为文件包含所有已安装应用的信息,所以我们尝试安装一个App(com.softard.test),并且查看其信息:

packages.list

com.softard.test 10052 1 /data/user/0/com.softard.test default none

这里10052是uid,至于其怎么生成的后面第二篇再详谈。

packages.xml


        
            
    

然后对App做个修改,将其改成系统App并签名放到system/app/Test下,再看这两个文件:

com.softard.test 1000 0 /data/user/0/com.softard.test platform 3009,3002,1023,1015,3003,3001,1021,1000,2002,2950,1010,1007

看到uid变成了1000,selinux从default变成platform,权限组从none变成3009,3002,1023,1015,3003,3001,1021,1000,2002,2950,1010,1007。而且应用一下子增加了一堆权限:

 
        
            
        
        
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
        
        
    

所以问题来了,改成系统应用后uid为什么变成1000?后面代表权限组的一串数字又都是什么?

0011 Android File Permission

android_filesystem_config.h

在Android中,所有权限的定义都在:system/core/include/private/android_filesystem_config.h

在这个头文件中定义了Android系统的一些用户,包含root用户,system用户,shell用户所对应的值等等。

/* This is the master Users and Groups config for the platform.
 * DO NOT EVER RENUMBER
 */

#define AID_ROOT             0  /* traditional unix root user */

#define AID_SYSTEM        1000  /* system server */

#define AID_RADIO         1001  /* telephony subsystem, RIL */
#define AID_BLUETOOTH     1002  /* bluetooth subsystem */
#define AID_GRAPHICS      1003  /* graphics devices */
#define AID_INPUT         1004  /* input devices */
#define AID_AUDIO         1005  /* audio devices */
#define AID_CAMERA        1006  /* camera devices */
#define AID_LOG           1007  /* log devices */
#define AID_COMPASS       1008  /* compass device */
#define AID_MOUNT         1009  /* mountd socket */
#define AID_WIFI          1010  /* wifi subsystem */
#define AID_ADB           1011  /* android debug bridge (adbd) */
#define AID_INSTALL       1012  /* group for installing packages */
#define AID_MEDIA         1013  /* mediaserver process */
#define AID_DHCP          1014  /* dhcp client */
#define AID_SDCARD_RW     1015  /* external storage write access */
#define AID_VPN           1016  /* vpn system */
#define AID_KEYSTORE      1017  /* keystore subsystem */
#define AID_USB           1018  /* USB devices */
#define AID_DRM           1019  /* DRM server */
#define AID_MDNSR         1020  /* MulticastDNSResponder (service discovery) */
#define AID_GPS           1021  /* GPS daemon */
#define AID_UNUSED1       1022  /* deprecated, DO NOT USE */
#define AID_MEDIA_RW      1023  /* internal media storage write access */
#define AID_MTP           1024  /* MTP USB driver access */
#define AID_UNUSED2       1025  /* deprecated, DO NOT USE */
#define AID_DRMRPC        1026  /* group for drm rpc */
#define AID_NFC           1027  /* nfc subsystem */
#define AID_SDCARD_R      1028  /* external storage read access */
#define AID_CLAT          1029  /* clat part of nat464 */
#define AID_LOOP_RADIO    1030  /* loop radio devices */
#define AID_MEDIA_DRM     1031  /* MediaDrm plugins */
#define AID_PACKAGE_INFO  1032  /* access to installed package details */
#define AID_SDCARD_PICS   1033  /* external storage photos access */
#define AID_SDCARD_AV     1034  /* external storage audio/video access */
#define AID_SDCARD_ALL    1035  /* access all users external storage */
#define AID_LOGD          1036  /* log daemon */
#define AID_SHARED_RELRO  1037  /* creator of shared GNU RELRO files */
#define AID_DBUS          1038  /* dbus-daemon IPC broker process */
#define AID_TLSDATE       1039  /* tlsdate unprivileged user */
#define AID_MEDIA_EX      1040  /* mediaextractor process */
#define AID_AUDIOSERVER   1041  /* audioserver process */
#define AID_METRICS_COLL  1042  /* metrics_collector process */
#define AID_METRICSD      1043  /* metricsd process */
#define AID_WEBSERV       1044  /* webservd process */
#define AID_DEBUGGERD     1045  /* debuggerd unprivileged user */
#define AID_MEDIA_CODEC   1046  /* mediacodec process */
#define AID_CAMERASERVER  1047  /* cameraserver process */
#define AID_FIREWALL      1048  /* firewalld process */
#define AID_TRUNKS        1049  /* trunksd process (TPM daemon) */
#define AID_NVRAM         1050  /* Access-controlled NVRAM */
#define AID_DNS           1051  /* DNS resolution daemon (system: netd) */
#define AID_DNS_TETHER    1052  /* DNS resolution daemon (tether: dnsmasq) */
/* Changes to this file must be made in AOSP, *not* in internal branches. */

#define AID_SHELL         2000  /* adb and debug shell user */
#define AID_CACHE         2001  /* cache access */
#define AID_DIAG          2002  /* access to diagnostic resources */

/* The range 2900-2999 is reserved for OEM, and must never be
 * used here */
#define AID_OEM_RESERVED_START 2900
#define AID_OEM_RESERVED_END   2999

/* The 3000 series are intended for use as supplemental group id's only.
 * They indicate special Android capabilities that the kernel is aware of. */
#define AID_NET_BT_ADMIN  3001  /* bluetooth: create any socket */
#define AID_NET_BT        3002  /* bluetooth: create sco, rfcomm or l2cap sockets */
#define AID_INET          3003  /* can create AF_INET and AF_INET6 sockets */
#define AID_NET_RAW       3004  /* can create raw INET sockets */
#define AID_NET_ADMIN     3005  /* can configure interfaces and routing tables. */
#define AID_NET_BW_STATS  3006  /* read bandwidth statistics */
#define AID_NET_BW_ACCT   3007  /* change bandwidth statistics accounting */
#define AID_NET_BT_STACK  3008  /* bluetooth: access config files */
#define AID_READPROC      3009  /* Allow /proc read access */
#define AID_WAKELOCK      3010  /* Allow system wakelock read/write access */

/* The range 5000-5999 is also reserved for OEM, and must never be used here. */
#define AID_OEM_RESERVED_2_START 5000
#define AID_OEM_RESERVED_2_END   5999

#define AID_EVERYBODY     9997  /* shared between all apps in the same profile */
#define AID_MISC          9998  /* access to misc storage */
#define AID_NOBODY        9999

#define AID_APP          10000  /* first app user */

#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
#define AID_ISOLATED_END   99999 /* end of uids for fully isolated sandboxed processes */

#define AID_USER        100000  /* offset for uid ranges for each user */

#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
#define AID_SHARED_GID_END   59999 /* start of gids for apps in each user to share */

从头文件定义,就知道每个权限组都是由一串数字代表的。除了数字,该文件还定义了一个结构体数组,映射数字对应的字符串:

static const struct android_id_info android_ids[] = {
    { "root",          AID_ROOT, },

    { "system",        AID_SYSTEM, },

    { "radio",         AID_RADIO, },
    { "bluetooth",     AID_BLUETOOTH, },
    { "graphics",      AID_GRAPHICS, },
    { "input",         AID_INPUT, },
    { "audio",         AID_AUDIO, },
    { "camera",        AID_CAMERA, },
    { "log",           AID_LOG, },
    { "compass",       AID_COMPASS, },
    { "mount",         AID_MOUNT, },
    { "wifi",          AID_WIFI, },
    { "adb",           AID_ADB, },
    { "install",       AID_INSTALL, },
    { "media",         AID_MEDIA, },
    { "dhcp",          AID_DHCP, },
    { "sdcard_rw",     AID_SDCARD_RW, },
    { "vpn",           AID_VPN, },
    { "keystore",      AID_KEYSTORE, },
    { "usb",           AID_USB, },
    { "drm",           AID_DRM, },
    { "mdnsr",         AID_MDNSR, },
    { "gps",           AID_GPS, },
    // AID_UNUSED1
    { "media_rw",      AID_MEDIA_RW, },
    { "mtp",           AID_MTP, },
    // AID_UNUSED2
    { "drmrpc",        AID_DRMRPC, },
    { "nfc",           AID_NFC, },
    { "sdcard_r",      AID_SDCARD_R, },
    { "clat",          AID_CLAT, },
    { "loop_radio",    AID_LOOP_RADIO, },
    { "mediadrm",      AID_MEDIA_DRM, },
    { "package_info",  AID_PACKAGE_INFO, },
    { "sdcard_pics",   AID_SDCARD_PICS, },
    { "sdcard_av",     AID_SDCARD_AV, },
    { "sdcard_all",    AID_SDCARD_ALL, },
    { "logd",          AID_LOGD, },
    { "shared_relro",  AID_SHARED_RELRO, },
    { "dbus",          AID_DBUS, },
    { "tlsdate",       AID_TLSDATE, },
    { "mediaex",       AID_MEDIA_EX, },
    { "audioserver",   AID_AUDIOSERVER, },
    { "metrics_coll",  AID_METRICS_COLL },
    { "metricsd",      AID_METRICSD },
    { "webserv",       AID_WEBSERV },
    { "debuggerd",     AID_DEBUGGERD, },
    { "mediacodec",    AID_MEDIA_CODEC, },
    { "cameraserver",  AID_CAMERASERVER, },
    { "firewall",      AID_FIREWALL, },
    { "trunks",        AID_TRUNKS, },
    { "nvram",         AID_NVRAM, },
    { "dns",           AID_DNS, },
    { "dns_tether",    AID_DNS_TETHER, },

    { "shell",         AID_SHELL, },
    { "cache",         AID_CACHE, },
    { "diag",          AID_DIAG, },

    { "net_bt_admin",  AID_NET_BT_ADMIN, },
    { "net_bt",        AID_NET_BT, },
    { "inet",          AID_INET, },
    { "net_raw",       AID_NET_RAW, },
    { "net_admin",     AID_NET_ADMIN, },
    { "net_bw_stats",  AID_NET_BW_STATS, },
    { "net_bw_acct",   AID_NET_BW_ACCT, },
    { "net_bt_stack",  AID_NET_BT_STACK, },
    { "readproc",      AID_READPROC, },
    { "wakelock",      AID_WAKELOCK, },

    { "everybody",     AID_EVERYBODY, },
    { "misc",          AID_MISC, },
    { "nobody",        AID_NOBODY, },
};

好了,了解这个文件我们再来看我们应用的信息:

com.softard.test 1000 0 /data/user/0/com.softard.test platform 3009,3002,1023,1015,3003,3001,1021,1000,2002,1010,1007

我们把数字对应的信息截取下来:

#define AID_SYSTEM        1000  "system"    /* system server */        
#define AID_LOG           1007  "log"        /* log devices */        
#define AID_WIFI          1010  "wifi"        /* wifi subsystem */    
#define AID_SDCARD_RW     1015  "sdcard_rw"    /* external storage write access */
#define AID_GPS           1021  "gps"        /* GPS daemon */
#define AID_MEDIA_RW      1023  "media_rw"    /* internal media storage write access */
#define AID_DIAG          2002  "diag"        /* access to diagnostic resources */
#define AID_NET_BT_ADMIN  3001  "net_bt_admin"/* bluetooth: create any socket */
#define AID_NET_BT        3002  "net_bt"    /* bluetooth: create sco, rfcomm or l2cap sockets */
#define AID_INET          3003  "inet"        /* can create AF_INET and AF_INET6 sockets */
#define AID_READPROC      3009  "readproc"    /* Allow /proc read access */

所以,当我指定应用为系统应用时,就将uid指定为了1000。并且拥有了各种属于系统的权限组。

那么,指定系统应用后是怎么获得这一系列的gid呢?这一块源码流程很多,放到后面集中分析。

好了,现在我们了解system/core/include/private/android_filesystem_config.h文件定义以后,其实就前进了一大步。注意一下代码所在源码位置,位于system/core下,其实它已经是Android内核部分了,所以后面涉及到权限内容,都会导入这个头文件。

现在来看一段源码再来熟悉一下这部分内容:

FileUtils.setPermissions(fstr.getFD(), 0640, SYSTEM_UID, PACKAGE_INFO_GID);

这是位于frameworks/base/services/core/java/com/android/server/pm/Settings.java的一段代码,功能就是创建packages.list文件。从函数名称和参数可以知道,它是给文件添加权限的,通过这段代码可以推测出:它给packages.list文件赋予了0640的权限,权限隶属于system,权限组为package_info。

然后我们进入系统看一看是不是这样:

/data/system # ls -l packages.list
-rw-r----- 1 system package_info 13627 1970-01-01 11:27 packages.list

有没有发现原来Android底层权限其实也不是很难理解嘛?

这时,又有一个问题了,创建文件你可以这样设定权限,但系统文件/文件夹的默认权限又是从哪来的?这就要引入另外一个文件了。

fs_config.c

写过Android App的你肯定知道,App的一些数据都放在/data/data目录下。正常情况下这个目录是不可以访问的:

/data/data $ ls
ls: .: Permission denied

我们看一下这个目录的权限:

/data/data $ ls -ld
drwxrwx--x 310 system system 12288 2019-01-11 09:51 .

我们作为shell用户,只有一个x权限, 当然访问不了。那如果我要给shell赋予访问权限改怎么改呢?

这就需要了解一下system/core/libcutils/fs_config.c文件了。系统目录和文件的用户组以及权限都是在这个文件里定义的:

/* Rules for directories.
** These rules are applied based on "first match", so they
** should start with the most specific path and work their
** way up to the root.
*/
static const struct fs_path_config android_dirs[] = {
    { 00770, AID_SYSTEM, AID_CACHE,  0, "cache" },
    { 00500, AID_ROOT,   AID_ROOT,   0, "config" },
    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },
    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-ephemeral" },
    { 00771, AID_ROOT,   AID_ROOT,   0, "data/dalvik-cache" },
    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },
    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local/tmp" },
    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local" },
    { 01771, AID_SYSTEM, AID_MISC,   0, "data/misc" },
    { 00770, AID_DHCP,   AID_DHCP,   0, "data/misc/dhcp" },
    { 00771, AID_SHARED_RELRO, AID_SHARED_RELRO, 0, "data/misc/shared_relro" },
    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
    { 00750, AID_ROOT,   AID_SHELL,  0, "data/nativetest" },
    { 00750, AID_ROOT,   AID_SHELL,  0, "data/nativetest64" },
    { 00775, AID_ROOT,   AID_ROOT,   0, "data/preloads" },
    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
    { 00755, AID_ROOT,   AID_SYSTEM, 0, "mnt" },
    { 00755, AID_ROOT,   AID_ROOT,   0, "root" },
    { 00750, AID_ROOT,   AID_SHELL,  0, "sbin" },
    { 00751, AID_ROOT,   AID_SDCARD_R, 0, "storage" },
    { 00755, AID_ROOT,   AID_SHELL,  0, "system/bin" },
    { 00755, AID_ROOT,   AID_SHELL,  0, "system/vendor" },
    { 00755, AID_ROOT,   AID_SHELL,  0, "system/xbin" },
    { 00755, AID_ROOT,   AID_ROOT,   0, "system/etc/ppp" },
    { 00755, AID_ROOT,   AID_SHELL,  0, "vendor" },
    { 00777, AID_ROOT,   AID_ROOT,   0, "sdcard" },
    { 00755, AID_ROOT,   AID_ROOT,   0, 0 },
};

/* Rules for files.
** These rules are applied based on "first match", so they
** should start with the most specific path and work their
** way up to the root. Prefixes ending in * denotes wildcard
** and will allow partial matches.
*/
static const char conf_dir[] = "/system/etc/fs_config_dirs";
static const char conf_file[] = "/system/etc/fs_config_files";

static const struct fs_path_config android_files[] = {
    { 00440, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.rc" },
    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.sh" },
    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.ril" },
    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
    { 00440, AID_ROOT,      AID_ROOT,      0, "system/etc/recovery.img" },
    { 00444, AID_ROOT,      AID_ROOT,      0, conf_dir + 1 },
    { 00444, AID_ROOT,      AID_ROOT,      0, conf_file + 1 },
    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app/*" },
    { 00644, AID_MEDIA_RW,  AID_MEDIA_RW,  0, "data/media/*" },
    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-private/*" },
    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-ephemeral/*" },
    { 00644, AID_APP,       AID_APP,       0, "data/data/*" },
    { 00640, AID_ROOT,      AID_SHELL,     0, "data/nativetest/tests.txt" },
    { 00640, AID_ROOT,      AID_SHELL,     0, "data/nativetest64/tests.txt" },
    { 00750, AID_ROOT,      AID_SHELL,     0, "data/nativetest/*" },
    { 00750, AID_ROOT,      AID_SHELL,     0, "data/nativetest64/*" },

    /* the following two files are INTENTIONALLY set-uid, but they
     * are NOT included on user builds. */
    { 04750, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
    { 06755, AID_ROOT,      AID_ROOT,      0, "system/xbin/procmem" },

    /* the following files have enhanced capabilities and ARE included in user builds. */
    { 00750, AID_ROOT,      AID_SHELL,     CAP_MASK_LONG(CAP_SETUID) | CAP_MASK_LONG(CAP_SETGID), "system/bin/run-as" },
    { 00700, AID_SYSTEM,    AID_SHELL,     CAP_MASK_LONG(CAP_BLOCK_SUSPEND), "system/bin/inputflinger" },

    /* Support FIFO scheduling mode in SurfaceFlinger. */
    { 00755, AID_SYSTEM,    AID_GRAPHICS,     CAP_MASK_LONG(CAP_SYS_NICE), "system/bin/surfaceflinger" },

    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/uncrypt" },
    { 00750, AID_ROOT,      AID_ROOT,      0, "system/bin/install-recovery.sh" },
    { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib/valgrind/*" },
    { 00755, AID_ROOT,      AID_ROOT,      0, "system/lib64/valgrind/*" },
    { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
    { 00755, AID_ROOT,      AID_SHELL,     0, "system/vendor/bin/*" },
    { 00755, AID_ROOT,      AID_SHELL,     0, "system/vendor/xbin/*" },
    { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
    { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/xbin/*" },
    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/*" },
    { 00755, AID_ROOT,      AID_ROOT,      0, "bin/*" },
    { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
    { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/fs_mgr" },
    { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
    { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
};

感觉也不用多说,android_dirs[]负责文件夹的权限配置,android_files[]负责文件的权限配置。

从里面定义找找刚提到的/data/data目录

{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },

你看,就是这么回事儿而已。如果要改成shell权限的话,只需要这样改就可以了:

{ 00771, AID_SYSTEM, AID_SHELL, 0, "data/data" },

当然,如果系统里还要添加其他目录、文件需要指定权限,只需要在这个文件里添加一行即可。

0100 Android App Permission

讲到这里,还遗留一个开头提出的问题:

为什么你在AndroidManifest文件请求storage权限你就可以访问设备文件?

0010里提到过,PackageManagerService在启动后会扫描所有已经安装的App,然后加载和解析他们的Androidmanifest文件,生成packages.listpackages.xml等文件。解析过程就包括了permission的解析与拦截。

frameworks/base/core/res/AndroidManifest.xml 这个文件中定义了Permission拦截规则,下面列举几个:









这里看一下protectionLevel,normal是一般权限,即不需要动态申请,直接在Manifest里注册即可获得的权限。dangerous是敏感权限,需要动态申请告知用户才能获取的权限。signature|privileged一般是系统priv-app才拥有的权限,也就是拥有系统签名的系统应用。

他的拦截规则大概是,如果App申请了signature|privileged权限,但他是普通开发者的三方App,PMS就会将其从申请权限的列表里将该权限删除。这样你的App实际上就没有获得对应的权限了。

那么,文件属性的权限是怎么和Permission联系起来的?不出意外,系统也有一个关联文件的定义frameworks/base/data/etc/platform.xml




    
    
    

    

    
        
    

    
        
    

    
        
        
    

    
        
    

    
        
    

    
        
    

    
        
        
    

    
        
    

    
        
    

    
    
        
    

    
    
        
        
    

    
    
        
    

    
    
        
    

    
        
    

    
    
        
    

    
        
        
    

    
    
    

    
    
    

    

    
    
    
    
    
    

    
    
    
    
    

    
    
    
    
    

    

    

    
    
    

    
    

    
    

    
    

    
    

这个文件定义了所有权限所属的gid。从里面找一下READ_EXTERNAL_STORAGE权限,emmmm,什么都没做。这是因为6.0之后存储权限变成动态,需要用户确认才可以获取权限,所以这里不作处理。动态权限这部分代码先不分析了,来看一下老版本的文件:


    

那明确了,READ_EXTERNAL_STORAGE权限获取的gid是sdcard_r,然后查看上面的文件定义,对应AID_SDCARD_R,数值是1028。实际上在7.0上得到的是sdcard_rw,即1015。

PMS在解析每个Permission时会根据这个文件将Permission关联的gid 加入到一个gid的数组中去,从而硬件设备所对应的设备文件就能被该应用程序访问。这块具体代码流程放到下一篇去分析。想自己跟代码的话可以从该函数看起:

private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds,
                                              String[] grantedPermissions) {
    for (int userId : userIds) {
        grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions);
    }

    // We could have touched GID membership, so flush out packages.list
    synchronized (mPackages) {
        mSettings.writePackageListLPr();
    }
}

回到存储权限,既然系统会根据permission给App添加合适的gid,那么我们在看下内置存储的权限为

/sdcard # ls -ld
drwxrwx--x 27 root sdcard_rw 4096 1970-01-01 18:30 .

所以获得sdcard_rw权限组的应用才可以访问内置存储。

到此Android权限的底层实现原理简单介绍完了,不过目前这里还留有一个坑,那就是我在测试App里添加STORAGE权限后,安装到设备里,通过查看进程属性,发现:

# ps | grep softard
u0_a53    3530  638   969076 30720 binder_thr b07244fc S com.softard.test
# cat /proc/3530/status
Name:    com.softard.test
State:    S (sleeping)
Tgid:    3530
Pid:    3530
PPid:    638
TracerPid:    0
Uid:    10053    10053    10053    10053
Gid:    10053    10053    10053    10053
Ngid:    0
FDSize:    256
Groups:    9997 50053

Groups没有对应的gid,但是程序的确可以访问/sdcard

然后我又给App系统签名,作为系统应用放进去再看,

# ps | grep soft
system    3560  629   985352 49184 SyS_epoll_ abea53b8 S com.softard.test
# cat /proc/3560/status
Name:    com.softard.test
State:    S (sleeping)
Tgid:    3560
Pid:    3560
PPid:    629
TracerPid:    0
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
Ngid:    0
FDSize:    256
Groups:    1000 1007 1010 1015 1021 1023 2002 2950 3001 3002 3003 3009 9997 41000

这时候Groups有sdcard_rw权限了。然后从设置里手动关掉存储权限,App无法读取文件,再次检查gid发现这个1015依旧存在。

WTF,7.0的表现跟5.0完全不一样?又是一个坑…后面抽空再填吧…

行吧,这篇概览就这样了,后面就开始从眼花缭乱的源码角度去看这一切的实现。

0101 Reference

Android文件属性的权限和Permission的联系


文章作者: Wossoneri
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC 4.0 许可协议。转载请注明来源 Wossoneri !
评论
  目录